package com.bxs.handler;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bxs.global.LogLevel;
import com.bxs.mapper.FrequentRecordMapper;
import com.bxs.mapper.RecordMapper;
import com.bxs.pojo.FrequentRecord;
import com.bxs.pojo.Record;
import com.bxs.utils.TimeUtils;
import org.pcap4j.core.PcapPacket;
import org.pcap4j.packet.IcmpV4CommonPacket;
import org.pcap4j.packet.IpPacket;
import org.pcap4j.packet.TcpPacket;
import org.pcap4j.packet.UdpPacket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 记录数据报来源的访问频率
 */
@Component
public class FrequentPacketHandler extends BasePacketHandler{
    @Value("${ids.frequent-interval}")
    Integer frequentInterval;

    @Value("${ids.frequent-edge}")
    Integer frequentEdge;

    @Autowired
    FrequentRecordMapper frequentRecordMapper;

    @Autowired
    RecordMapper recordMapper;

    @Override
    public void handle(PcapPacket packet) {
        // 跳过非Ipv4数据包
        IpPacket ipPacket = packet.get(IpPacket.class);
        if (ipPacket == null)return;
        ArrayList<String> protocols = new ArrayList<>();
        protocols.add("IPv4");
        // 解析ip信息
        FrequentRecord frequentRecord = new FrequentRecord();
        frequentRecord.setSourceIp(ipPacket.getHeader().getSrcAddr().getHostName());
        frequentRecord.setTargetIp(ipPacket.getHeader().getDstAddr().getHostName());
        System.out.println("receive: from " + frequentRecord.getSourceIp() + ", to: " + frequentRecord.getTargetIp());
        // 检测是否为TCP报文
        TcpPacket tcpPacket = packet.get(TcpPacket.class);
        if (tcpPacket != null){
            frequentRecord.setSourcePort(tcpPacket.getHeader().getSrcPort().valueAsInt());
            frequentRecord.setTargetPort(tcpPacket.getHeader().getDstPort().valueAsInt());
            protocols.add("TCP");
        }

        // 检测是否为UDP报文
        UdpPacket udpPacket = packet.get(UdpPacket.class);
        if(udpPacket != null){
            frequentRecord.setSourcePort(udpPacket.getHeader().getSrcPort().valueAsInt());
            frequentRecord.setTargetPort(udpPacket.getHeader().getDstPort().valueAsInt());
            protocols.add("UDP");
        }

        //
        IcmpV4CommonPacket icmpV4CommonPacket = packet.get(IcmpV4CommonPacket.class);
        if(icmpV4CommonPacket != null){
            protocols.add("ICMPv4");
        }

        // 生成时间信息
        Date date = TimeUtils.generateIntervalTime(new Date(), frequentInterval);
        frequentRecord.setUpdateTime(date);

        // 如果已存在
        QueryWrapper<FrequentRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("source_ip", frequentRecord.getSourceIp());
        queryWrapper.eq("target_ip", frequentRecord.getTargetIp());
        queryWrapper.eq("update_time", frequentRecord.getUpdateTime());
        List<FrequentRecord> frequentRecords = frequentRecordMapper.selectList(queryWrapper);
        if (frequentRecords.size() > 0){
            FrequentRecord t = frequentRecords.get(0);
            t.setCount(t.getCount() + 1);
            if (t.getCount() > frequentEdge){
                Record record = new Record();
                record.setLogLevel(LogLevel.DANGER.getCode());
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                record.setDescription("主机访问过于频繁, 访问次数: {" + t.getCount()+ "}, 访问开始时间：{" +
                        simpleDateFormat.format(frequentRecord.getUpdateTime()) + "}" +
                        ", 协议类型：{" + protocols + "}"
                );
                record.setSourceIp(frequentRecord.getSourceIp());
                record.setTargetIp(frequentRecord.getTargetIp());
                record.setSourcePort(frequentRecord.getSourcePort());
                record.setTargetPort(frequentRecord.getTargetPort());
                recordMapper.insert(record);
            }
            frequentRecordMapper.updateById(t);
        }else{
            frequentRecordMapper.insert(frequentRecord);
        }
    }
}
